home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 04 - 1988 / 04.11 Nov 88 / fast rotate source / rotate.a < prev    next >
Encoding:
Text File  |  1988-05-18  |  11.8 KB  |  390 lines  |  [TEXT/MPS ]

  1.     INCLUDE    'SysEqu.a'    ;the usual system equates & macros    
  2.     INCLUDE    'Traps.a'
  3.     INCLUDE    'QuickEqu.a'
  4.     
  5. newPtrClear FUNC EXPORT
  6.     
  7.     IMPORT    SAVERETA1
  8.     
  9.     MOVE.L    (SP)+,A1
  10.     MOVE.L    (SP)+,D0
  11.     _NewPtr    clear
  12.     MOVE.L    A0,(SP)
  13.     JMP    SAVERETA1
  14.     
  15.     ENDF
  16.  
  17.  
  18. Rotate PROC EXPORT
  19. ;------------------------------------------------------------------------
  20. ;    
  21. ; PROCEDURE    Rotate (sourceMap, destMap : bitMap );
  22. ;    
  23. ; given a source and destination bitmap rotate it CCW 90°…
  24. ; bitmap can be of any size, we will align on a word boundaries (v & h)
  25. ;
  26. ;-------------------------------------------------------------------------------
  27. ;    a0 = result of _newPtr call            |    d0 = size of bitMap to allocate
  28. ;    a1 = ptr to src bitMap                |    d1 = width/2  (source)
  29. ;    a2 = ptr to dest bitMap                |    d2 = height/2 (source)
  30. ;    a3 = dest bits                        |    d3 = left | top
  31. ;    a4 = copy of dest bits                |    d4 = ctrPt.h
  32. ;    a5 = not used                        |    d5 = ctrPt.v
  33. ;    a6 = not used                        |    d6 = right | bottom
  34. ;    a7 = not used                        |    d7 = rowBytes of dest bitMap
  35. ;-------------------------------------------------------------------------------
  36. ; ***********************************************************************
  37. ; *                                                                        *
  38. ; *        Initialize destination bitMap (destMap), etc…                    *
  39. ; *                                                                        *
  40. ; ***********************************************************************
  41. ; parameter offsets
  42. ;
  43. DestMap        EQU    4+4                ; offset to dest bitmap ^
  44. SourceMap    EQU DestMap + 4        ; offset to source bitmap ^
  45. ;
  46. ; create local stack frame, and save some registers
  47. ; make room for dest rect to be passed back
  48. ;
  49.     link    a6,#0                ; set up a stack frame (no bytes)
  50.     movem.l    d3-d7/a2-a5,-(sp)    ; save registers pascal may need
  51.  
  52.     move.l    SourceMap(a6),a1    ; point to the source BitMap
  53.     move.l    DestMap(a6),a2        ; point to the dest BitMap
  54. ;
  55. ; compute height of source BitMap rounded up to nearest word
  56. ;                                
  57.     move.w    bounds+bottom(a1),d7; get bottom and put in d7
  58.     sub.w    bounds+top(a1),d7    ; bottom - top = height, put in d7
  59.     move.w    d7,d0                ; save a copy of height for later
  60.                                 ; rnd = (height+15)/16, follows:
  61.     addi.w    #15,d7                ; add 15 to the height, put in d7
  62.     lsr        #4,d7                ; divide by 16
  63.     lsl        #1,d7                ; multiply by 2 = rowBytes of dest bitMap
  64. ;
  65. ; d7 now contains rowBytes of dest bitMap
  66. ;
  67. ; now compute the destRect for dest bitMap
  68. ;
  69.                                 ; compute center point of Source rect
  70.                                 ; note the center points are not necess. the
  71.                                 ; same in the vert dir. relative to srcMap
  72.                                 ; because of rounding that follows (i.e. height
  73.                                 ; of srcMap is dir. prop. to RowBytes of destMap)
  74.     lsr        #1,d0                ; divide height by 2
  75.     move.w    d0,d2                ; make a copy of height/2 for later
  76.     move.w    bounds+top(a1),d5    ; get 'top' of source rect
  77.     add.w    d0,d5                ; d5 now contains vert component of ctr pt
  78.                                 ; compute the width of src rect & put in d4
  79.     move.w    bounds+right(a1),d3    ; get right and put in d3
  80.     sub.w    bounds+left(a1),d3    ; right - left = width, put in d3
  81.     lsr        #1,d3                ; divide width by 2
  82.     move.w    d3,d1                ; make a copy of width/2 for later
  83.     move.w    bounds+right(a1),d4    ; get right of source rect
  84.     sub.w    d3,d4                ; d4 now contains horiz component of ctr pt
  85. ;
  86. ; now get center point and compute bounds for dest bitMap
  87. ; height and width are reversed now for the 2 bitMaps
  88. ;
  89. ; left    :=ctrPt.h - height/2
  90. ; top    :=ctrPt.v - width/2
  91. ; right    :=ctrPt.h + height/2
  92. ; bottom:=ctrPt.v + width/2
  93. ; SetRect(rect, left, top, right, bottom) put data in direct to
  94. ; avoid the overhead of a trap call
  95. ;
  96.                                 ; compute 'top'
  97.     move.w    d5,d3                ; get a copy of ctrPt.v and put in d3
  98.     sub.w    d1,d3                ; ctrPt.v - width/2 = 'top' in d3
  99.     swap    d3                    ; move 'top' to hiword
  100.                                 ; compute 'left'
  101.     move.w    d4,d3                ; get a copy of ctrPt.h and put in loword d3
  102.     sub.w    d2,d3                ; ctrPt.h - height/2 = 'left' in loword d3
  103. ;
  104. ; we now have 'top' in hiword & 'left' in loword d3
  105. ;
  106.                                 ; compute 'bottom'
  107.     move.w    d5,d6                ; get a copy of ctrPt.v in of d3
  108.     add.w    d1,d6                ; ctrPt.v + width/2 = 'bottom' in d3
  109.     swap    d6                    ; move 'bottom' to hiword    
  110.                                 ; compute 'right'
  111.     move.w    d4,d6                ; get a copy of ctrPt.h and put in loword d6
  112.     add.w    d2,d6                ; ctrPt.h + height/2 = 'right' in loword d6
  113. ;
  114. ; we now have 'bottom' in hiword & 'right' in loword d6
  115. ;
  116. ; assign data to dest bitMap structure directly
  117. ;
  118.     move.w    d7,rowBytes(a2)        ; put in rowBytes direct for dest bitMap
  119.     move.l    d3,bounds+topLeft(a2)    ; put the coord pair in direct
  120.     move.l    d6,bounds+botRight(a2)    ; put the coord pair in direct
  121.     move.w    d7,d0                ; put rowbytes in d0
  122.     mulu    rowBytes(a1),d0        ; multiply rowBytes src*dest = d0
  123.     lsl        #3,d0                ; multiply d0 by 8 for size of dest bitMap
  124.     _NewPtr    clear                ; allocate size of dest bitMap (a2 pts to it) 
  125.     move.l    a0,baseaddr(a2)        ; move contents of a0 to baseAddr field
  126.                                 ; of dest bitMap structure
  127.                                 
  128. ;-------------------------------------------------------------------------------
  129. ;    a0 = baseAddr for our locals        |    d0 = rowbytes of srcMap
  130. ;    a1 = points to bits of src bitMap    |    d1 = width/2     (source)
  131. ;    a2 = ptr to dest bitMap                |    d2 = height/2      (source)
  132. ;    a3 = dest bits                        |    d3 = current word srcMap
  133. ;    a4 =                                 |    d4 = copy of width of srcMap
  134. ;    a5 = not used                        |    d5 = current destMap word
  135. ;    a6 = not used                        |    d6 = insideLoop count (current bit)
  136. ;    a7 = not used                        |    d7 = rowBytes of dest bitMap
  137. ;-------------------------------------------------------------------------------
  138. ; ***********************************************************************
  139. ; *                                                                        *
  140. ; *        Start actual rotation of bitMaps                                *
  141. ; *                                                                        *
  142. ; ***********************************************************************
  143. ; Assumptions:
  144. ; height of destination bitMap = rowBytes of srcMap
  145. ;
  146. ; Get the baseAddr for our locals into a0 - this will make our program much
  147. ; more readable as we will let the assembler do all the addr location calcs
  148. ; for us. The addresses will be a fixed number while the programs is
  149. ; (locked down) and running, therefore, there is no runtime penalty for
  150. ; doing this addr calculation
  151. ;
  152.  
  153.     lea    localVars,a0
  154.  
  155.     ; Synchronize with the TickCount rollover.
  156.     move.l    ticks, d0            ; get the time
  157. @1    cmp.l    ticks, d0            ; changed yet?
  158.     beq.s    @1                    ; nope: loop
  159.  
  160.     ; Strobe the starting time.
  161.     move.l    ticks, startTime-localVars(a0) ; save starting time, in ticks
  162.  
  163. ;
  164. ; initialize d0 to contain the pointer to the srcMap
  165. ;
  166.     move.w    rowbytes(a1),d0        ; get rowbytes of srcMap
  167.     
  168. ;
  169. ; get regs pointing to bits
  170. ;
  171.     move.l    (a1),a1                ; a1 pts to BITS of src bitMap    
  172.     move.l    (a2),a3                ; a3 pts to BITS of dest bitMap
  173.  
  174. ; compute the lower left corner of the destMap - this maps to the upper left
  175. ; corner of the srcMap and will be used as base from which to offset into
  176. ; the dest map when we need to set a bit
  177. ;
  178.     clr.l    d1                    ; clear d1 
  179.     move.w    d0,d1                ; load rowBytes of srcMap
  180.                                 ; (rowBytes of srcMap = ht of destMap)
  181.     lsl.w    #3,d1                ; multiply by 8 to get ht of destMap when rot'd
  182.     mulu.w    d7,d1                ; multiply by rowbytes(destMap) = #words in
  183.     sub.w    d7,d1                ; destMap less one row
  184.     add.l    a3,d1                ; add the computed offset to the baseAddr of destMap
  185.     move.l    d1,lowerLeft-localVars(a0)    ; init lowerLeft
  186. ;
  187. ;-------------------------------------------------------------------------------
  188. ;    a0 = baseAddr for our locals        |    d0 = rowbytes of srcMap
  189. ;    a1 = points to bits of src bitMap    |    d1 = SCRATCH
  190. ;    a2 = SCRATCH                        |    d2 = colmCounter
  191. ;    a3 = dest bits                        |    d3 = current srcMap word 
  192. ;    a4 = SCRATCH                        |    d4 = colmBitLoop counter
  193. ;    a5 = not used                        |    d5 = current word destMap
  194. ;    a6 = not used                        |    d6 = insideLoop count (current bit)
  195. ;    a7 = not used                        |    d7 = rowBytes of dest bitMap
  196. ;-------------------------------------------------------------------------------
  197. ;
  198.  
  199. ;    _Debugger;
  200.     
  201. ; init wordCount to zero 
  202. ;
  203.     move.w    #0,wordCount-localVars(a0)    ; set wordCount to one before we start
  204. ;
  205. ; init colmLoop counter
  206. ;
  207.     move.w    d7,d2                ; get rowBytes(dest)
  208.     lsr        #1,d2                ; divide by 2 - d2 now contains the outer counter
  209.     move.w    d2,colmCount-localVars(a0)    ; put the max value away for reference
  210.     moveq.l    #0,d2                ; set d2 to zero since we use it for the counter
  211.  
  212. colmLoop
  213. ;
  214. ; this is the outside loop
  215. ;
  216.     move.w    #15,d4                ; init colmBitLoop counter to 15
  217.     move.l    lowerLeft-localVars(a0), a2    ; init currentWord    
  218.  
  219. colmBitLoop
  220. ;
  221. ; this is the loop that does the bit counting in the destMap - it is really a
  222. ; misuse of the 'dbra' instruction since it is not an independent loop but it
  223. ; is a quite cheap method of doing our counting
  224. ;
  225.  
  226.     cmp.w    #7, d4                        ; are we doing high byte or low?
  227.     bgt        dobyte1                        ; skip if high byte
  228.     addq    #1, a2                        ; else point to low byte
  229. dobyte1
  230.  
  231. rowLoop
  232. ;
  233. ; loop across each row in the srcMap and keep count each time we do a row
  234. ; this 'rowCount' will used to compute the offset from 'lowerLeft'
  235. ;
  236.     move.w    (a1)+, d3                    ; get a word to rotate into d3
  237.     addq.w    #2,wordCount-localVars(a0)    ; add 1 for each word •••jdo•••
  238.     
  239.     add.w    d3, d3                        ; test next bit in the current source word
  240.     bcc.s    NoBitToChange                ; if bit’s not set, skip to next
  241.     bset    d4, (a2)                    ; set proper bit in high or low byte in currentWord
  242. noBitToChange
  243.     sub.l    d7, a2                        ; subtract rowBytes(destMap) from current word
  244.  
  245.     ; Do the same as above, fifteen more times.
  246.     add.w    d3, d3
  247.     bcc.s    @1
  248.     bset    d4, (a2)
  249. @1    sub.l    d7, a2
  250.  
  251.     add.w    d3, d3
  252.     bcc.s    @2
  253.     bset    d4, (a2)
  254. @2    sub.l    d7, a2
  255.  
  256.     add.w    d3, d3
  257.     bcc.s    @3
  258.     bset    d4, (a2)
  259. @3    sub.l    d7, a2
  260.  
  261.     add.w    d3, d3
  262.     bcc.s    @4
  263.     bset    d4, (a2)
  264. @4    sub.l    d7, a2
  265.  
  266.     add.w    d3, d3
  267.     bcc.s    @5
  268.     bset    d4, (a2)
  269. @5    sub.l    d7, a2
  270.  
  271.     add.w    d3, d3
  272.     bcc.s    @6
  273.     bset    d4, (a2)
  274. @6    sub.l    d7, a2
  275.  
  276.     add.w    d3, d3
  277.     bcc.s    @7
  278.     bset    d4, (a2)
  279. @7    sub.l    d7, a2
  280.  
  281.     add.w    d3, d3
  282.     bcc.s    @8
  283.     bset    d4, (a2)
  284. @8    sub.l    d7, a2
  285.  
  286.     add.w    d3, d3
  287.     bcc.s    @9
  288.     bset    d4, (a2)
  289. @9    sub.l    d7, a2
  290.  
  291.     add.w    d3, d3
  292.     bcc.s    @10
  293.     bset    d4, (a2)
  294. @10    sub.l    d7, a2
  295.  
  296.     add.w    d3, d3
  297.     bcc.s    @11
  298.     bset    d4, (a2)
  299. @11    sub.l    d7, a2
  300.  
  301.     add.w    d3, d3
  302.     bcc.s    @12
  303.     bset    d4, (a2)
  304. @12    sub.l    d7, a2
  305.  
  306.     add.w    d3, d3
  307.     bcc.s    @13
  308.     bset    d4, (a2)
  309. @13    sub.l    d7, a2
  310.  
  311.     add.w    d3, d3
  312.     bcc.s    @14
  313.     bset    d4, (a2)
  314. @14    sub.l    d7, a2
  315.  
  316.     add.w    d3, d3
  317.     bcc.s    @15
  318.     bset    d4, (a2)
  319. @15    sub.l    d7, a2
  320.  
  321. ;
  322. ; at this point we've just completed a word from the srcMap
  323. ;
  324.     cmp        wordCount-localVars(a0),d0        ; cmp wordCount to rowBytes-are we done with a row ?
  325.     bne        rowLoop                            ; no - do another word
  326.     
  327.     cmp.w    #7, d4                        ; did we do high byte or low?
  328.     bgt        dobyte2                        ; skip if high byte
  329.     subq    #1, a2                        ; else undo the fudge to a2
  330. dobyte2
  331.  
  332. ;
  333. ; we just completed a row so add 2 to the count
  334. ;
  335.     move.w    #0,wordCount-localVars(a0)        ; •••jdo••• reset wordCount to zero
  336.  
  337. ;    
  338. ; the following use of dbra keeps track of our destMap bit for us
  339. ;
  340.     move.l    lowerLeft-localVars(a0), a2    ; re-init currentWord    
  341.                                         ; set the currentWord to the lowerLeft(current)
  342.                                         ; lowerLeft is moved over (right) by a word each
  343.                                         ; time we do a row in the srcMap
  344.     dbra    d4,colmBitLoop                ; go thru the bits (15->0) in the
  345.                                         ; destMap - then exit and do it
  346.                                         ; again for rowBytes/2 times
  347.  
  348. ;
  349. ; were done counting thru the bits of a destMap word - at this point we have
  350. ; actually finished a column in the destMap. The column is a multiple of
  351. ; 16 bits wide (and being at least 1 colm) and as tall as the destMap is
  352. ; (which is also equal to rowBytes of the srcMap)
  353. ;
  354.     addq.l    #2,lowerLeft-localVars(a0)        ; this moves us into the next
  355.                                             ; 'column' of bits in the destMap
  356.     addq.w    #1,d2                            ; add 1 to the colmLoop counter
  357.     cmp        colmCount-localVars(a0),d2        ; are we done yet ?
  358.     bne        colmLoop                        ; no - do it again
  359.                                             ; else we're done
  360. ;
  361. ; were done so lets do our clean-up/restore and go away gracefully
  362. ;
  363.     move.l    ticks, d0            ; get the current time…
  364.     sub.l    startTime-localVars(a0), d0 ; …less starting time
  365.     _Debugger                    ; and let me see the time it took
  366.  
  367.     movem.l    (sp)+,d3-d7/a2-a5    ; restore registers
  368.     unlk    a6                    ; clean up stack frame
  369.     move.l    (sp)+,a0            ; return address
  370.     add.l    #8,sp                ; pop parameters off stack
  371.     jmp        (a0)                 ; bye y'all!
  372.     
  373. ;
  374. ; set up our data storage area
  375. ;
  376. localVars                        ; the beginning of our local var storage area
  377. colmCount        ds.w    1
  378. currentWord        ds.l    1
  379. lowerLeft        ds.l    1
  380. wordCount        ds.w    1
  381. startTime        ds.l    1
  382.  
  383.     ENDP
  384.     
  385.     END
  386.     
  387.  
  388.